<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="js/vue.js"></script>
	</head>
	<style type="text/css">
	    * {
	        margin: 0;
	        padding: 0;
	        box-sizing: border-box;
	        list-style: none;
	    }
	
	    ul {
	        width: 310px;
	        background-color: #2144e2;
	        display: flex;
	        flex-wrap: wrap;
	        margin: 30px auto;
	        border: 5px solid #568411;
	        border-radius: 5px;
	    }
	
	    li {
	        width: 100px;
	        height: 100px;
	        background-color: #E4B77C;
	        border: 1px solid #542113;
	        text-align: center;
	        line-height: 100px;
	        font-weight: bold;
	    }
	
	    .number0 {
	        /* 空白格的样式 */
	        opacity: 0;
	    }
	
	    button {    
	        padding: 10px 20px;
	        background: #421C0F;
	        background-color: #421C0F;
	        color: #fff;
	        border-radius: 5px;
	        display: block;
	        margin: 10px auto;
	    }
	
	    .list-move {
	        transition: 0.5s;
	    }
	</style>
	<body>
		<div id='app'>
		    <transition-group tag="ul" name="list">
		        <li :class="'number' + item" v-for='(item, index) in list' @click="move(index)" :key="item">
				{{ item > 0 ? item : '' }}</li>
		    </transition-group>
		    <button @click="start">开始游戏</button>
		</div>
<script>
        Vue.createApp({
            data() {
                return {
                    list: [1, 2, 3, 4, 5, 6, 7, 8, 0]
                };
            },
            methods: {
                start() {
                    // 打乱数组顺序
                    this.list.sort(() => Math.random() - 0.5);
                    // 检查是否有解，如果无解则重新打乱
                    while (!this.isSolvable(this.list)) {
                        this.list.sort(() => Math.random() - 0.5);
                    }
                },
                move(i) {
                    // 找到空白格的索引
                    const emptyIndex = this.list.indexOf(0);
                    // 上下左右的相邻格子索引
                    const neb = [i - 3, i + 3, i - 1, i + 1];
                    // 检查是否存在右边格子
                    if (parseInt(i / 3) !== parseInt(neb[3] / 3)) {
                        neb[3] = -1;
                    }
                    // 检查是否存在左边格子
                    if (parseInt(i / 3) !== parseInt(neb[2] / 3)) {
                        neb[2] = -1;
                    }
                    // 检查相邻格子是否为空白格
                    for (let j = 0; j < neb.length; j++) {
                        if (neb[j] === emptyIndex) {
                            // 交换当前格子和空白格的位置
                            [this.list[i], this.list[emptyIndex]] = [this.list[emptyIndex], this.list[i]];
                            // 检查是否完成游戏
                            if (this.isGameOver()) {
                                alert('恭喜你，游戏完成！');
                            }
                            break;
                        }
                    }
                },
                isSolvable(arr) {
                    // 计算逆序数
                    let inversions = 0;
                    const len = arr.length;
                    for (let i = 0; i < len; i++) {
                        for (let j = i + 1; j < len; j++) {
                            if (arr[i] !== 0 && arr[j] !== 0 && arr[i] > arr[j]) {
                                inversions++;
                            }
                        }
                    }
                    // 对于 3x3 的数字华容道，逆序数为偶数则有解
                    return inversions % 2 === 0;
                },
                isGameOver() {
                    // 检查是否完成游戏
                    for (let i = 0; i < this.list.length - 1; i++) {
                        if (this.list[i] !== i + 1) {
                            return false;
                        }
                    }
                    return this.list[this.list.length - 1] === 0;
                }
            }
        }).mount('#app');
    </script>
	</body>
</html>